/**
 * 
 */
package com.lehecai.ucenter.service.impl.app;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lehecai.core.exception.cache.CacheException;
import com.lehecai.core.service.cache.CacheService;
import com.lehecai.ucenter.dao.QueryParam;
import com.lehecai.ucenter.dao.app.AppDao;
import com.lehecai.ucenter.dao.permission.UserAppDao;
import com.lehecai.ucenter.entity.app.App;
import com.lehecai.ucenter.entity.permission.UserApp;
import com.lehecai.ucenter.service.app.AppService;
import com.lehecai.ucenter.utils.PageBean;

/**
 * @author qatang
 *
 */
public class AppServiceImpl implements AppService {
	protected final Logger logger = LoggerFactory.getLogger(this.getClass());
	private final static String CACHE_KEY_PREFIX = "app_";
	private AppDao appDao;
	private UserAppDao userAppDao;
	private CacheService cacheService;
	private String cacheName;
	
	@Override
	public App get(Long id) {
		App app = this.getFromCacheOnly(id);
		if (app != null) {
			// 从缓存中取到值，直接返回
			return app;
		}
		
		// 如果未从缓存中取到值
		synchronized (this) {
			// 加锁后先再取一次，保证只被set一次
			app = this.getFromCacheOnly(id);
			if (app != null) {
				// 从缓存中取到值，直接返回
				return app;
			}
			// 如果还未取到值，获取原始数据
			app = appDao.get(id);
			if (app != null) {
				try {
					cacheService.setObject(cacheName, this.generateKey(id), app);
				} catch (CacheException e) {
					logger.error("设置缓存出错, key={}", this.generateKey(id));
					logger.error(e.getMessage(), e);
				}
				return app;
			}
		}
		return null;
	}
	
	@Override
	public App getFormDb(Long id) {
		return appDao.get(id);
	}
	
	@Override
	public App update(App app) {
		appDao.merge(app);
		App cacheApp = this.getFromCacheOnly(app.getId());
		if (cacheApp != null) {
			try {
				cacheService.remove(cacheName,  this.generateKey(cacheApp.getId()));
			} catch (CacheException e) {
				logger.error("删除缓存出错, key={}", this.generateKey(cacheApp.getId()));
				logger.error(e.getMessage(), e);
			}
		}
		return null;
	}

	@Override
	public List<App> findList(QueryParam queryParam) {
		List<App> apps = appDao.findList(queryParam);
		int totalCount = appDao.count(queryParam);
		PageBean pageBean = queryParam.getPageBean();
		if(pageBean != null){
			pageBean.setCount(totalCount);
			int pageCount = 0;//页数
			if(pageBean.getPageSize() != 0) {
	            pageCount = totalCount / pageBean.getPageSize();
	            if(totalCount % pageBean.getPageSize() != 0) {
	                pageCount ++;
	            }
	        }
			pageBean.setPageCount(pageCount);
		}
		return apps;
	}

	@Override
	public void delete(App app) {
		appDao.delete(app);
		App cacheApp = this.getFromCacheOnly(app.getId());
		if (cacheApp != null) {
			try {
				cacheService.remove(cacheName,  this.generateKey(cacheApp.getId()));
			} catch (CacheException e) {
				logger.error("删除缓存出错, key={}", this.generateKey(cacheApp.getId()));
				logger.error(e.getMessage(), e);
			}
		}
		
		QueryParam queryParam = new QueryParam();
		queryParam.setParameter(UserApp.APP_ID_PROPERTY_NAME, app.getId());
		List<UserApp> userApps = userAppDao.findList(queryParam);
		if(userApps != null && !userApps.isEmpty()) {
			for(UserApp ua : userApps){
				userAppDao.delete(ua);
			}
		}
	}

	@Override
	public App findByToken(String token) {
		QueryParam queryParam = new QueryParam();
		queryParam.setParameter(App.TOKEN_PROPERTY_NAME, token);
		List<App> list = appDao.findList(queryParam);
		if (list != null && list.size() != 0) {
			return (App)list.get(0);
		}else{
			return null;
		}
	}
	
	protected String generateKey(Long id) {
		return CACHE_KEY_PREFIX + id;
	}
	
	protected App getFromCacheOnly(Long id) {
		App app = null;
		try {
			app = cacheService.getObject(App.class, cacheName, this.generateKey(id));
		} catch (CacheException e) {
			logger.error("从缓存中读取归档id出错, key={}", this.generateKey(id));
			logger.error(e.getMessage(), e);
		}
		return app;
	}

	public AppDao getAppDao() {
		return appDao;
	}

	public void setAppDao(AppDao appDao) {
		this.appDao = appDao;
	}

	public void setCacheService(CacheService cacheService) {
		this.cacheService = cacheService;
	}

	public void setCacheName(String cacheName) {
		this.cacheName = cacheName;
	}

	public UserAppDao getUserAppDao() {
		return userAppDao;
	}

	public void setUserAppDao(UserAppDao userAppDao) {
		this.userAppDao = userAppDao;
	}
}
